package de.jmda.gen.java.impl;

import static de.jmda.gen.java.naming.ImportManagerProvider.getImportManager;

import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.validation.constraints.NotNull;

import de.jmda.gen.java.DeclaredElementGenerator;
import de.jmda.gen.java.DeclaredFieldGenerator;
import de.jmda.gen.java.FieldGenerator;
import de.jmda.gen.java.FieldModifiersGenerator;
import de.jmda.gen.java.ModifiersUtil.VisibilityModifier;

/**
 * @author roger.jmda@gmail.com
 */
public abstract class AbstractFieldGenerator
		extends AbstractDeclarationGenerator
		implements FieldGenerator
{
	private DeclaredFieldGenerator declaredFieldGenerator;

	public AbstractFieldGenerator()
  {
		this(null);
  }

	/**
	 * @param generator
	 */
	public AbstractFieldGenerator(@NotNull DeclaredFieldGenerator generator)
  {
	  super();

	  if (generator == null)
	  {
	  	generator = new DefaultDeclaredInstanceFieldGenerator();
	  }

	  setDeclaredFieldGenerator(generator);

	  setComponentSeparator(System.lineSeparator());
  }

	@Override
  public DeclaredFieldGenerator getDeclaredFieldGenerator()
  {
	  return declaredFieldGenerator;
  }

	@Override
  public void setDeclaredFieldGenerator(DeclaredFieldGenerator generator)
  {
		if (generator == null)
		{
			return;
		}

		declaredFieldGenerator = generator;
  }

	@Override
  public DeclaredElementGenerator getDeclaredElementGenerator()
  {
	  return getDeclaredFieldGenerator();
  }

	@Override
  public void addAnnotation(@NotNull Class< ? > annotation)
  {
		demandAnnotationStatementsGenerator()
				.getAnnotationStatementGenerators()
				.add(new DefaultAnnotationStatementGenerator(annotation));
  }

	@Override
  public void setType(@NotNull TypeElement type)
  {
		getDeclaredFieldGenerator().setTypeNameGenerator(
				new DefaultTypeNameGenerator(getImportManager().useType(type)));
  }

	@Override
  public void setType(@NotNull TypeMirror type)
  {
		getDeclaredFieldGenerator().setTypeNameGenerator(
				new DefaultTypeNameGenerator(getImportManager().useType(type)));
  }

	@Override
  public void setType(@NotNull Class<?> type)
  {
		getDeclaredFieldGenerator().setTypeNameGenerator(
				new DefaultTypeNameGenerator(getImportManager().useType(type)));
  }

	@Override
  public void setType(@NotNull String name)
  {
		getDeclaredFieldGenerator().setTypeNameGenerator(
				new DefaultTypeNameGenerator(getImportManager().useType(name)));
  }

	@Override
  public void setTypeFrom(@NotNull VariableElement variableElement)
  {
		getDeclaredFieldGenerator().setTypeNameGenerator(
				new DefaultTypeNameGenerator(
						getImportManager().useTypeOf(variableElement)));
  }

	@Override
  public void setName(@NotNull String name)
  {
		getDeclaredFieldGenerator().setFieldNameGenerator(
				new DefaultFieldNameGenerator(name));
  }

	@Override
  public void setName(@NotNull Name name)
  {
		setName(name.toString());
  }

	@Override
  public void setVisibility(VisibilityModifier modifier)
  {
		FieldModifiersGenerator modifiersGenerator =
				getDeclaredFieldGenerator().demandModifiersGenerator();
		
		if (modifier == VisibilityModifier.DEFAULT)
		{
			// do nothing
		}
		else if (modifier == VisibilityModifier.PRIVATE)
		{
			modifiersGenerator.setPrivate(true);
		}
		else if (modifier == VisibilityModifier.PROTECTED)
		{
			modifiersGenerator.setProtected(true);
		}
		else if (modifier == VisibilityModifier.PUBLIC)
		{
			modifiersGenerator.setPublic(true);
		}
  }
}